import { Canvas, Path } from "@shopify/react-native-skia";
import { useMemo } from "react";
import { StyleSheet, View } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
  Easing,
  useAnimatedStyle,
  useDerivedValue,
  useSharedValue,
  withTiming,
} from "react-native-reanimated";

// 宫格手柄位置
type HandleDirection = "top" | "bottom" | "left" | "right";

interface GridHandle {
  position: HandleDirection;
}

// 生成宫格手柄路径
const getGridHandlePath = (
  handle: GridHandle,
  containerWidth: number,
  containerHeight: number
): string => {
  "worklet";
  const edgeWidth = 35; // 增加边缘手柄宽度
  const edgeHeight = 6; // 增加边缘手柄厚度
  const radius = 3; // 增加圆角

  switch (handle.position) {
    case "top":
      const topX = containerWidth / 2;
      const topY = 0;
      return `M ${topX - edgeWidth / 2 + radius} ${topY} Q ${
        topX - edgeWidth / 2
      } ${topY} ${topX - edgeWidth / 2} ${topY + radius} L ${
        topX - edgeWidth / 2
      } ${topY + edgeHeight - radius} Q ${topX - edgeWidth / 2} ${
        topY + edgeHeight
      } ${topX - edgeWidth / 2 + radius} ${topY + edgeHeight} L ${
        topX + edgeWidth / 2 - radius
      } ${topY + edgeHeight} Q ${topX + edgeWidth / 2} ${topY + edgeHeight} ${
        topX + edgeWidth / 2
      } ${topY + edgeHeight - radius} L ${topX + edgeWidth / 2} ${
        topY + radius
      } Q ${topX + edgeWidth / 2} ${topY} ${
        topX + edgeWidth / 2 - radius
      } ${topY} Z`;

    case "bottom":
      const bottomX = containerWidth / 2;
      const bottomY = containerHeight;
      return `M ${bottomX - edgeWidth / 2 + radius} ${bottomY} Q ${
        bottomX - edgeWidth / 2
      } ${bottomY} ${bottomX - edgeWidth / 2} ${bottomY - radius} L ${
        bottomX - edgeWidth / 2
      } ${bottomY - edgeHeight + radius} Q ${bottomX - edgeWidth / 2} ${
        bottomY - edgeHeight
      } ${bottomX - edgeWidth / 2 + radius} ${bottomY - edgeHeight} L ${
        bottomX + edgeWidth / 2 - radius
      } ${bottomY - edgeHeight} Q ${bottomX + edgeWidth / 2} ${
        bottomY - edgeHeight
      } ${bottomX + edgeWidth / 2} ${bottomY - edgeHeight + radius} L ${
        bottomX + edgeWidth / 2
      } ${bottomY - radius} Q ${bottomX + edgeWidth / 2} ${bottomY} ${
        bottomX + edgeWidth / 2 - radius
      } ${bottomY} Z`;

    case "left":
      const leftX = 0;
      const leftY = containerHeight / 2;
      return `M ${leftX} ${leftY - edgeWidth / 2 + radius} Q ${leftX} ${
        leftY - edgeWidth / 2
      } ${leftX + radius} ${leftY - edgeWidth / 2} L ${
        leftX + edgeHeight - radius
      } ${leftY - edgeWidth / 2} Q ${leftX + edgeHeight} ${
        leftY - edgeWidth / 2
      } ${leftX + edgeHeight} ${leftY - edgeWidth / 2 + radius} L ${
        leftX + edgeHeight
      } ${leftY + edgeWidth / 2 - radius} Q ${leftX + edgeHeight} ${
        leftY + edgeWidth / 2
      } ${leftX + edgeHeight - radius} ${leftY + edgeWidth / 2} L ${
        leftX + radius
      } ${leftY + edgeWidth / 2} Q ${leftX} ${leftY + edgeWidth / 2} ${leftX} ${
        leftY + edgeWidth / 2 - radius
      } Z`;

    case "right":
      const rightX = containerWidth;
      const rightY = containerHeight / 2;
      return `M ${rightX} ${rightY - edgeWidth / 2 + radius} Q ${rightX} ${
        rightY - edgeWidth / 2
      } ${rightX - radius} ${rightY - edgeWidth / 2} L ${
        rightX - edgeHeight + radius
      } ${rightY - edgeWidth / 2} Q ${rightX - edgeHeight} ${
        rightY - edgeWidth / 2
      } ${rightX - edgeHeight} ${rightY - edgeWidth / 2 + radius} L ${
        rightX - edgeHeight
      } ${rightY + edgeWidth / 2 - radius} Q ${rightX - edgeHeight} ${
        rightY + edgeWidth / 2
      } ${rightX - edgeHeight + radius} ${rightY + edgeWidth / 2} L ${
        rightX - radius
      } ${rightY + edgeWidth / 2} Q ${rightX} ${
        rightY + edgeWidth / 2
      } ${rightX} ${rightY + edgeWidth / 2 - radius} Z`;

    default:
      return "";
  }
};

// 宫格手势层组件
interface GridGestureHandlerProps {
  gridCell: {
    x: number;
    y: number;
    width: number;
    height: number;
    row: number;
    col: number;
  };
  isSelected?: boolean;
  selectedCellSV: import("react-native-reanimated").SharedValue<{
    row: number;
    col: number;
  } | null>;
  selectedRectSV: import("react-native-reanimated").SharedValue<{
    x: number;
    y: number;
    width: number;
    height: number;
  } | null>;
  doubleTapSignalSV: import("react-native-reanimated").SharedValue<number>;
  menuVisibleSV: import("react-native-reanimated").SharedValue<number>;
  menuXSV: import("react-native-reanimated").SharedValue<number>;
  menuYSV: import("react-native-reanimated").SharedValue<number>;
  cols: number;
  rows: number;
  outerMargin: number;
  spacing: number;
  canvasWidth: number;
  canvasHeight: number;
  rowColWidthsSV?: import("react-native-reanimated").SharedValue<number[][]>;
  rowHeightsSV?: import("react-native-reanimated").SharedValue<number[]>;
  colRowHeightsSV?: import("react-native-reanimated").SharedValue<number[][]>;
  firstRowOffsetSV?: import("react-native-reanimated").SharedValue<number>;
  firstColOffsetSV?: import("react-native-reanimated").SharedValue<number>;

  onDragResize?: (
    direction: HandleDirection,
    translationX: number,
    translationY: number
  ) => void;
}

export const GridGestureHandler = ({
  gridCell,
  isSelected = false,
  selectedCellSV,
  selectedRectSV,
  doubleTapSignalSV,
  menuVisibleSV,
  menuXSV,
  menuYSV,
  cols,
  rows,
  outerMargin,
  spacing,
  canvasWidth,
  canvasHeight,
  rowColWidthsSV,
  rowHeightsSV,
  colRowHeightsSV,
  firstRowOffsetSV,
  firstColOffsetSV,

  onDragResize,
}: GridGestureHandlerProps) => {
  const handles: GridHandle[] = [
    { position: "top" },
    { position: "bottom" },
    { position: "left" },
    { position: "right" },
  ];

  // 使用 UI 线程共享值识别单双击并写入状态，避免 runOnJS
  const lastTapTs = useSharedValue(0);

  const combinedGesture = useMemo(
    () =>
      Gesture.Tap()
        // .maxDelay(320)
        // .maxDuration(320)
        .onEnd(() => {
          "worklet";
          const now = Date.now();
          const delta = now - (lastTapTs.value || 0);
          const DOUBLE_THRESHOLD = 280; // ms
          if (delta > 0 && delta <= DOUBLE_THRESHOLD) {
            // 双击：选中并发信号
            selectedCellSV.value = { row: gridCell.row, col: gridCell.col };
            selectedRectSV.value = {
              x: gridCell.x,
              y: gridCell.y,
              width: gridCell.width,
              height: gridCell.height,
            };
            doubleTapSignalSV.value = doubleTapSignalSV.value + 1;
            menuVisibleSV.value = 1;
            menuXSV.value = gridCell.x;
            menuYSV.value = gridCell.y;
            lastTapTs.value = 0;
          } else {
            // 单击：选中
            lastTapTs.value = now;
            selectedCellSV.value = { row: gridCell.row, col: gridCell.col };
            selectedRectSV.value = {
              x: gridCell.x,
              y: gridCell.y,
              width: gridCell.width,
              height: gridCell.height,
            };
          }
        })
        .simultaneousWithExternalGesture(
          Gesture.Tap(),
          Gesture.Pan(),
          Gesture.Pinch()
        ), // 允许与所有手势同时工作
    [
      doubleTapSignalSV,
      gridCell.col,
      gridCell.row,
      gridCell.x,
      gridCell.y,
      gridCell.width,
      gridCell.height,
      lastTapTs,
      selectedCellSV,
      selectedRectSV,
      menuVisibleSV,
      menuXSV,
      menuYSV,
    ]
  );

  // 计算当前单元格基于 sharedValue 的位置与尺寸（UI 线程）
  const cellRectDV = useDerivedValue(() => {
    "worklet";
    const widthsMatrix = rowColWidthsSV?.value || [];
    const heightsMatrix = colRowHeightsSV?.value || [];
    if (!widthsMatrix.length || !heightsMatrix.length) {
      return {
        x: gridCell.x,
        y: gridCell.y,
        width: gridCell.width,
        height: gridCell.height,
      };
    }
    // x/width: 来自当前行的列宽数组
    let x = outerMargin;
    const rowWidths = widthsMatrix[gridCell.row] || [];
    for (let i = 0; i < gridCell.col; i++) x += (rowWidths[i] || 0) + spacing;
    const width = rowWidths[gridCell.col] ?? gridCell.width;

    // y/height: 来自当前列的行高数组
    let y = outerMargin;
    const colHeights = heightsMatrix[gridCell.col] || [];
    for (let j = 0; j < gridCell.row; j++) y += (colHeights[j] || 0) + spacing;
    const height = colHeights[gridCell.row] ?? gridCell.height;

    // 不应用偏移量，保持其他宫格位置固定

    return { x, y, width, height };
  });

  const containerPosStyle = useAnimatedStyle(() => {
    const r = cellRectDV.value as any;
    return { left: r.x, top: r.y, width: r.width, height: r.height } as any;
  });

  const borderPathDV = useDerivedValue(() => {
    "worklet";
    const r = cellRectDV.value as any;
    return `M 0 0 L ${r.width} 0 L ${r.width} ${r.height} L 0 ${r.height} Z`;
  });

  // 视觉手柄路径（随当前尺寸变化）
  const handleTopPathDV = useDerivedValue(() => {
    "worklet";
    const r = cellRectDV.value as any;
    return getGridHandlePath({ position: "top" } as any, r.width, r.height);
  });
  const handleBottomPathDV = useDerivedValue(() => {
    "worklet";
    const r = cellRectDV.value as any;
    return getGridHandlePath({ position: "bottom" } as any, r.width, r.height);
  });
  const handleLeftPathDV = useDerivedValue(() => {
    "worklet";
    const r = cellRectDV.value as any;
    return getGridHandlePath({ position: "left" } as any, r.width, r.height);
  });
  const handleRightPathDV = useDerivedValue(() => {
    "worklet";
    const r = cellRectDV.value as any;
    return getGridHandlePath({ position: "right" } as any, r.width, r.height);
  });

  // 创建拖动手势（与视觉层分离）：始终存在，但仅在当前格子被选中时响应
  const createDragGesture = (direction: HandleDirection) => {
    "worklet";
    return Gesture.Pan()
      .minDistance(8)
      .onBegin(() => {
        "worklet";
        const sel = selectedCellSV.value;
        if (!sel || sel.row !== gridCell.row || sel.col !== gridCell.col) {
          // 未选中该格子：忽略拖动
          return;
        }
      })
      .onChange((e) => {
        "worklet";
        const sel = selectedCellSV.value;
        if (!sel || sel.row !== gridCell.row || sel.col !== gridCell.col)
          return;
        // 纯 UI 线程：直接在共享值上修改列宽/行高，不桥接到 JS
        const MIN_SIZE = 60;
        const SENSITIVITY = 1;
        const MIN_STEP = 1;
        if (direction === "right" || direction === "left") {
          // 水平拖动：寻找Y轴对齐的宫格组合
          if (
            !Array.isArray(rowColWidthsSV?.value) ||
            !Array.isArray(colRowHeightsSV?.value)
          )
            return;
          const widths = rowColWidthsSV!.value.map((r) => r.slice());
          const heightsByCol = colRowHeightsSV!.value.map((ca) => ca.slice());
          const r = gridCell.row;
          const c = gridCell.col;
          const neighborCol = direction === "right" ? c + 1 : c - 1;
          let delta =
            (direction === "right" ? e.changeX : -e.changeX) * SENSITIVITY;
          if (!isFinite(delta) || Math.abs(delta) < MIN_STEP) return;

          // 边界：没有邻居时检查画布边界
          if (neighborCol < 0 || neighborCol >= widths[r].length) {
            if (delta > 0) {
              // 向外扩展：检查是否超出画布边界
              const totalRowWidth =
                widths[r].reduce((sum, w) => sum + w, 0) +
                (widths[r].length - 1) * spacing;
              const availableWidth = canvasWidth - outerMargin * 2;
              if (totalRowWidth + delta > availableWidth) return; // 超出画布

              // 可以向外扩展
              widths[r][c] = Math.max(MIN_SIZE, widths[r][c] + delta);
              rowColWidthsSV!.value = widths;
              return;
            } else {
              // 向内收缩：只影响当前宫格，不调整其他宫格
              const canShrink = Math.max(0, widths[r][c] - MIN_SIZE);
              const take = Math.min(-delta, canShrink);
              if (take <= 0) return;

              // 只修改当前宫格的宽度，其他宫格位置保持不变
              widths[r][c] = Math.max(MIN_SIZE, widths[r][c] - take);
              rowColWidthsSV!.value = widths;
              return;
            }
          }

          // 计算拖动宫格的Y坐标范围
          let draggedCellYStart = outerMargin;
          for (let rr = 0; rr < r; rr++)
            draggedCellYStart += (heightsByCol[c][rr] || 0) + spacing;
          const draggedCellYEnd = draggedCellYStart + (heightsByCol[c][r] || 0);

          // 计算拖动宫格与相邻宫格的高度
          const draggedCellHeight = draggedCellYEnd - draggedCellYStart;
          const neighborCellHeight = heightsByCol[neighborCol][r] || 0;

          const affectedRows: number[] = [];

          if (draggedCellHeight >= neighborCellHeight) {
            // 拖动宫格高度大于等于相邻宫格：使用Y轴重叠检测
            // 递归检测所有有交集的行
            const detectOverlappingRows = () => {
              const newAffectedRows: number[] = [];

              // 检测拖动列中哪些行与相邻列有交集
              for (let rr = 0; rr < rows; rr++) {
                // 计算拖动列当前行的Y坐标范围
                let draggedColRowYStart = outerMargin;
                for (let rrr = 0; rrr < rr; rrr++) {
                  draggedColRowYStart += (heightsByCol[c][rrr] || 0) + spacing;
                }
                const draggedColRowYEnd =
                  draggedColRowYStart + (heightsByCol[c][rr] || 0);

                // 检查与相邻列的所有行是否有交集
                for (let neighborRow = 0; neighborRow < rows; neighborRow++) {
                  // 计算相邻列当前行的Y坐标范围
                  let neighborColRowYStart = outerMargin;
                  for (let rrr = 0; rrr < neighborRow; rrr++) {
                    neighborColRowYStart +=
                      (heightsByCol[neighborCol][rrr] || 0) + spacing;
                  }
                  const neighborColRowYEnd =
                    neighborColRowYStart +
                    (heightsByCol[neighborCol][neighborRow] || 0);

                  // 检查Y轴是否重叠（Y坐标范围有交集）
                  if (
                    draggedColRowYStart < neighborColRowYEnd &&
                    draggedColRowYEnd > neighborColRowYStart
                  ) {
                    // 如果拖动列的行还没有被影响，且相邻列的行已经被影响，则添加拖动列的行
                    if (
                      !affectedRows.includes(rr) &&
                      affectedRows.includes(neighborRow)
                    ) {
                      newAffectedRows.push(rr);
                    }
                    // 如果相邻列的行还没有被影响，且拖动列的行已经被影响，则添加相邻列的行
                    else if (
                      !affectedRows.includes(neighborRow) &&
                      affectedRows.includes(rr)
                    ) {
                      newAffectedRows.push(neighborRow);
                    }
                  }
                }
              }

              return newAffectedRows;
            };

            // 首先添加初始碰撞的行
            affectedRows.push(r);

            // 递归检测直到没有新的交集
            let hasNewOverlaps = true;
            while (hasNewOverlaps) {
              const newRows = detectOverlappingRows();
              if (newRows.length > 0) {
                affectedRows.push(...newRows);
                hasNewOverlaps = true;
              } else {
                hasNewOverlaps = false;
              }
            }
          } else {
            // 递归检测所有有交集的行
            const detectOverlappingRows = () => {
              const newAffectedRows: number[] = [];

              // 检测拖动列中哪些行与相邻列有交集
              for (let rr = 0; rr < rows; rr++) {
                // 计算拖动列当前行的Y坐标范围
                let draggedColRowYStart = outerMargin;
                for (let rrr = 0; rrr < rr; rrr++) {
                  draggedColRowYStart += (heightsByCol[c][rrr] || 0) + spacing;
                }
                const draggedColRowYEnd =
                  draggedColRowYStart + (heightsByCol[c][rr] || 0);

                // 检查与相邻列的所有行是否有交集
                for (let neighborRow = 0; neighborRow < rows; neighborRow++) {
                  // 计算相邻列当前行的Y坐标范围
                  let neighborColRowYStart = outerMargin;
                  for (let rrr = 0; rrr < neighborRow; rrr++) {
                    neighborColRowYStart +=
                      (heightsByCol[neighborCol][rrr] || 0) + spacing;
                  }
                  const neighborColRowYEnd =
                    neighborColRowYStart +
                    (heightsByCol[neighborCol][neighborRow] || 0);

                  // 检查Y轴是否重叠（Y坐标范围有交集）
                  if (
                    draggedColRowYStart < neighborColRowYEnd &&
                    draggedColRowYEnd > neighborColRowYStart
                  ) {
                    // 如果拖动列的行还没有被影响，且相邻列的行已经被影响，则添加拖动列的行
                    if (
                      !affectedRows.includes(rr) &&
                      affectedRows.includes(neighborRow)
                    ) {
                      newAffectedRows.push(rr);
                    }
                    // 如果相邻列的行还没有被影响，且拖动列的行已经被影响，则添加相邻列的行
                    else if (
                      !affectedRows.includes(neighborRow) &&
                      affectedRows.includes(rr)
                    ) {
                      newAffectedRows.push(neighborRow);
                    }
                  }
                }
              }

              return newAffectedRows;
            };

            // 首先添加初始碰撞的行
            affectedRows.push(r);

            // 递归检测直到没有新的交集
            let hasNewOverlaps = true;
            while (hasNewOverlaps) {
              const newRows = detectOverlappingRows();
              if (newRows.length > 0) {
                affectedRows.push(...newRows);
                hasNewOverlaps = true;
              } else {
                hasNewOverlaps = false;
              }
            }
          }

          // 计算所有受影响行的最大可调整量
          let maxTake = Infinity;
          for (const affectedRow of affectedRows) {
            const canGive = Math.max(
              0,
              widths[affectedRow][neighborCol] - MIN_SIZE
            );
            const canShrink = Math.max(0, widths[affectedRow][c] - MIN_SIZE);
            if (delta > 0) {
              maxTake = Math.min(maxTake, canGive);
            } else {
              maxTake = Math.min(maxTake, canShrink);
            }
          }

          const take = Math.min(Math.abs(delta), maxTake);
          if (take <= 0) return;

          // 调整所有受影响行的宽度
          for (const affectedRow of affectedRows) {
            if (delta > 0) {
              widths[affectedRow][c] = Math.max(
                MIN_SIZE,
                widths[affectedRow][c] + take
              );
              widths[affectedRow][neighborCol] = Math.max(
                MIN_SIZE,
                widths[affectedRow][neighborCol] - take
              );
            } else {
              widths[affectedRow][c] = Math.max(
                MIN_SIZE,
                widths[affectedRow][c] - take
              );
              widths[affectedRow][neighborCol] =
                widths[affectedRow][neighborCol] + take;
            }
          }
          rowColWidthsSV!.value = widths;
        } else {
          // 垂直拖动：寻找X轴对齐的宫格组合
          if (
            !Array.isArray(colRowHeightsSV?.value) ||
            !Array.isArray(rowColWidthsSV?.value)
          )
            return;
          const heightsByCol = colRowHeightsSV!.value.map((col) => col.slice());
          const widthsByRow = rowColWidthsSV!.value.map((r) => r.slice());
          const r = gridCell.row;
          const c = gridCell.col;
          const neighborRow = direction === "bottom" ? r + 1 : r - 1;
          let delta =
            (direction === "bottom" ? e.changeY : -e.changeY) * SENSITIVITY;
          if (!isFinite(delta) || Math.abs(delta) < MIN_STEP) return;

          // 边界：没有邻居时检查画布边界
          if (
            neighborRow < 0 ||
            neighborRow >= (heightsByCol[c]?.length || 0)
          ) {
            if (delta > 0) {
              // 向外扩展：检查是否超出画布边界
              const totalColHeight =
                heightsByCol[c].reduce((sum, h) => sum + h, 0) +
                (heightsByCol[c].length - 1) * spacing;
              const availableHeight = canvasHeight - outerMargin * 2;
              if (totalColHeight + delta > availableHeight) return; // 超出画布

              // 可以向外扩展
              const after = colRowHeightsSV!.value.map((col) => col.slice());
              after[c][r] = Math.max(MIN_SIZE, after[c][r] + delta);
              colRowHeightsSV!.value = after;
              return;
            } else {
              // 向内收缩：只影响当前宫格，不调整其他宫格
              const canShrink = Math.max(
                0,
                (heightsByCol[c]?.[r] || 0) - MIN_SIZE
              );
              const take = Math.min(-delta, canShrink);
              if (take <= 0) return;

              // 只修改当前宫格的高度，其他宫格位置保持不变
              const after = colRowHeightsSV!.value.map((col) => col.slice());
              after[c][r] = Math.max(MIN_SIZE, after[c][r] - take);
              colRowHeightsSV!.value = after;
              return;
            }
          }

          // 计算拖动宫格的X坐标范围
          let draggedCellXStart = outerMargin;
          for (let cc = 0; cc < c; cc++)
            draggedCellXStart += (widthsByRow[r][cc] || 0) + spacing;
          const draggedCellXEnd = draggedCellXStart + (widthsByRow[r][c] || 0);

          // 计算拖动宫格与相邻宫格的宽度
          const draggedCellWidth = draggedCellXEnd - draggedCellXStart;
          const neighborCellWidth = widthsByRow[neighborRow][c] || 0;

          const affectedCols: number[] = [];

          if (draggedCellWidth >= neighborCellWidth) {
            // 递归检测所有有交集的列
            const detectOverlappingCols = () => {
              const newAffectedCols: number[] = [];

              // 检测拖动行中哪些列与相邻行有交集
              for (let cc = 0; cc < cols; cc++) {
                // 计算拖动行当前列的X坐标范围
                let draggedRowColXStart = outerMargin;
                for (let ccc = 0; ccc < cc; ccc++) {
                  draggedRowColXStart += (widthsByRow[r][ccc] || 0) + spacing;
                }
                const draggedRowColXEnd =
                  draggedRowColXStart + (widthsByRow[r][cc] || 0);

                // 检查与相邻行的所有列是否有交集
                for (let neighborCol = 0; neighborCol < cols; neighborCol++) {
                  // 计算相邻行当前列的X坐标范围
                  let neighborRowColXStart = outerMargin;
                  for (let ccc = 0; ccc < neighborCol; ccc++) {
                    neighborRowColXStart +=
                      (widthsByRow[neighborRow][ccc] || 0) + spacing;
                  }
                  const neighborRowColXEnd =
                    neighborRowColXStart +
                    (widthsByRow[neighborRow][neighborCol] || 0);

                  // 检查X轴是否重叠（X坐标范围有交集）
                  if (
                    draggedRowColXStart < neighborRowColXEnd &&
                    draggedRowColXEnd > neighborRowColXStart
                  ) {
                    // 如果拖动行的列还没有被影响，且相邻行的列已经被影响，则添加拖动行的列
                    if (
                      !affectedCols.includes(cc) &&
                      affectedCols.includes(neighborCol)
                    ) {
                      newAffectedCols.push(cc);
                    }
                    // 如果相邻行的列还没有被影响，且拖动行的列已经被影响，则添加相邻行的列
                    else if (
                      !affectedCols.includes(neighborCol) &&
                      affectedCols.includes(cc)
                    ) {
                      newAffectedCols.push(neighborCol);
                    }
                  }
                }
              }

              return newAffectedCols;
            };

            // 首先添加初始碰撞的列
            affectedCols.push(c);

            // 递归检测直到没有新的交集
            let hasNewOverlaps = true;
            while (hasNewOverlaps) {
              const newCols = detectOverlappingCols();
              if (newCols.length > 0) {
                affectedCols.push(...newCols);
                hasNewOverlaps = true;
              } else {
                hasNewOverlaps = false;
              }
            }
          } else {
            // 递归检测所有有交集的列
            const detectOverlappingCols = () => {
              const newAffectedCols: number[] = [];

              // 检测拖动行中哪些列与相邻行有交集
              for (let cc = 0; cc < cols; cc++) {
                // 计算拖动行当前列的X坐标范围
                let draggedRowColXStart = outerMargin;
                for (let ccc = 0; ccc < cc; ccc++) {
                  draggedRowColXStart += (widthsByRow[r][ccc] || 0) + spacing;
                }
                const draggedRowColXEnd =
                  draggedRowColXStart + (widthsByRow[r][cc] || 0);

                // 检查与相邻行的所有列是否有交集
                for (let neighborCol = 0; neighborCol < cols; neighborCol++) {
                  // 计算相邻行当前列的X坐标范围
                  let neighborRowColXStart = outerMargin;
                  for (let ccc = 0; ccc < neighborCol; ccc++) {
                    neighborRowColXStart +=
                      (widthsByRow[neighborRow][ccc] || 0) + spacing;
                  }
                  const neighborRowColXEnd =
                    neighborRowColXStart +
                    (widthsByRow[neighborRow][neighborCol] || 0);

                  // 检查X轴是否重叠（X坐标范围有交集）
                  if (
                    draggedRowColXStart < neighborRowColXEnd &&
                    draggedRowColXEnd > neighborRowColXStart
                  ) {
                    // 如果拖动行的列还没有被影响，且相邻行的列已经被影响，则添加拖动行的列
                    if (
                      !affectedCols.includes(cc) &&
                      affectedCols.includes(neighborCol)
                    ) {
                      newAffectedCols.push(cc);
                    }
                    // 如果相邻行的列还没有被影响，且拖动行的列已经被影响，则添加相邻行的列
                    else if (
                      !affectedCols.includes(neighborCol) &&
                      affectedCols.includes(cc)
                    ) {
                      newAffectedCols.push(neighborCol);
                    }
                  }
                }
              }

              return newAffectedCols;
            };

            // 首先添加初始碰撞的列
            affectedCols.push(c);

            // 递归检测直到没有新的交集
            let hasNewOverlaps = true;
            while (hasNewOverlaps) {
              const newCols = detectOverlappingCols();
              if (newCols.length > 0) {
                affectedCols.push(...newCols);
                hasNewOverlaps = true;
              } else {
                hasNewOverlaps = false;
              }
            }
          }

          // 计算所有受影响列的最大可调整量
          let maxTake = Infinity;
          for (const affectedCol of affectedCols) {
            const canGive = Math.max(
              0,
              heightsByCol[affectedCol][neighborRow] - MIN_SIZE
            );
            const canShrink = Math.max(
              0,
              heightsByCol[affectedCol][r] - MIN_SIZE
            );
            if (delta > 0) {
              maxTake = Math.min(maxTake, canGive);
            } else {
              maxTake = Math.min(maxTake, canShrink);
            }
          }

          const take = Math.min(Math.abs(delta), maxTake);
          if (take <= 0) return;

          // 调整所有受影响列的高度
          const after = colRowHeightsSV!.value.map((col) => col.slice());
          for (const affectedCol of affectedCols) {
            if (delta > 0) {
              after[affectedCol][r] = Math.max(
                MIN_SIZE,
                after[affectedCol][r] + take
              );
              after[affectedCol][neighborRow] = Math.max(
                MIN_SIZE,
                after[affectedCol][neighborRow] - take
              );
            } else {
              after[affectedCol][r] = Math.max(
                MIN_SIZE,
                after[affectedCol][r] - take
              );
              after[affectedCol][neighborRow] =
                after[affectedCol][neighborRow] + take;
            }
          }

          colRowHeightsSV!.value = after;
        }
      })
      .onEnd(() => {
        "worklet";
        const sel = selectedCellSV.value;
        if (!sel || sel.row !== gridCell.row || sel.col !== gridCell.col)
          return;
      });
  };

  return (
    <>
      {/* 点击选择区域（随当前格宽高实时变化）*/}
      <GestureDetector gesture={combinedGesture}>
        <Animated.View style={[styles.gridGestureArea, containerPosStyle]} />
      </GestureDetector>

      {/* 手柄拖动层（与视觉层分离）：与视觉层同显隐，由 shared value 控制 */}
      <Animated.View
        pointerEvents="box-none"
        style={[
          styles.dragOverlayContainer,
          containerPosStyle,
          useAnimatedStyle(() => {
            const sel = selectedCellSV.value;
            const visible =
              sel && sel.row === gridCell.row && sel.col === gridCell.col
                ? 1
                : 0;
            const opacity = withTiming(visible, {
              duration: 100,
              easing: Easing.out(Easing.quad),
            });
            return { opacity } as any;
          }),
        ]}
      >
        {/* 四个手柄命中区：使用 static View + 绝对定位（容器已跟随 cellRectDV）*/}
        <GestureDetector gesture={createDragGesture("top")}>
          <View style={styles.dragArea} pointerEvents="auto" />
        </GestureDetector>
        <GestureDetector gesture={createDragGesture("bottom")}>
          <View style={styles.dragAreaBottom} pointerEvents="auto" />
        </GestureDetector>
        <GestureDetector gesture={createDragGesture("left")}>
          <View style={styles.dragAreaLeft} pointerEvents="auto" />
        </GestureDetector>
        <GestureDetector gesture={createDragGesture("right")}>
          <View style={styles.dragAreaRight} pointerEvents="auto" />
        </GestureDetector>
      </Animated.View>

      {/* 视觉手柄 + 选中边框（无手势，仅显示/隐藏）*/}
      <Animated.View
        pointerEvents="none"
        style={[
          styles.gridOverlayContainer,
          containerPosStyle,
          useAnimatedStyle(() => {
            const sel = selectedCellSV.value;
            const visible =
              sel && sel.row === gridCell.row && sel.col === gridCell.col
                ? 1
                : 0;
            const opacity = withTiming(visible, {
              duration: 100,
              easing: Easing.out(Easing.quad),
            });
            const scale = withTiming(visible ? 1 : 0.98, {
              duration: 100,
              easing: Easing.out(Easing.quad),
            });
            return { opacity, transform: [{ scale }] } as any;
          }),
        ]}
      >
        <Canvas style={styles.handleCanvas} pointerEvents="none">
          <Path
            path={borderPathDV}
            color="#007AFF"
            style="stroke"
            strokeWidth={1}
          />
          <Path
            path={handleTopPathDV}
            color="rgba(0, 122, 255, 1)"
            style="fill"
          />
          <Path
            path={handleBottomPathDV}
            color="rgba(0, 122, 255, 1)"
            style="fill"
          />
          <Path
            path={handleLeftPathDV}
            color="rgba(0, 122, 255, 1)"
            style="fill"
          />
          <Path
            path={handleRightPathDV}
            color="rgba(0, 122, 255, 1)"
            style="fill"
          />
        </Canvas>
      </Animated.View>
    </>
  );
};

const styles = StyleSheet.create({
  gridGestureArea: {
    position: "absolute",
    // backgroundColor: "rgba(85, 16, 175, 0.91)", // 半透明绿色，用于调试
    zIndex: 2,
  },
  gridOverlayContainer: {
    position: "absolute",
    zIndex: 2,
    backgroundColor: "transparent",
  },
  dragOverlayContainer: {
    position: "absolute",
    zIndex: 3,
    backgroundColor: "transparent",
  },
  dragArea: {
    position: "absolute",
    // backgroundColor: "rgba(255, 0, 0, 0.3)",
    zIndex: 3,
    left: "50%",
    transform: [{ translateX: -20 }],
    top: 0,
    width: 40,
    height: 20,
  },
  dragAreaBottom: {
    position: "absolute",
    // backgroundColor: "rgba(255, 0, 0, 0.3)",
    zIndex: 3,
    left: "50%",
    transform: [{ translateX: -20 }],
    bottom: 0,
    width: 40,
    height: 20,
  },
  dragAreaLeft: {
    position: "absolute",
    // backgroundColor: "rgba(255, 0, 0, 0.3)",
    zIndex: 3,
    left: 0,
    top: "50%",
    transform: [{ translateY: -20 }],
    width: 20,
    height: 40,
  },
  dragAreaRight: {
    position: "absolute",
    // backgroundColor: "rgba(255, 0, 0, 0.3)",
    zIndex: 3,
    right: 0,
    top: "50%",
    transform: [{ translateY: -20 }],
    width: 20,
    height: 40,
  },
  handleCanvas: {
    position: "absolute",
    width: "100%",
    height: "100%",
  },
});
